import axios, { AxiosError, AxiosInstance, AxiosRequestConfig } from 'axios'
import { HOST } from './constance'
import { message } from 'antd'

// 扩展 InternalAxiosRequestConfig 接口
declare module 'axios' {
  interface InternalAxiosRequestConfig {
    metadata?: {
      startTime?: number
      endTime?: number
    }
  }
}

interface AxiosConfig extends AxiosRequestConfig {
  metadata: {
    startTime?: number
    endTime?: number
  }
}

interface IRequest {
  <T = any>(url: string, opts: any): Promise<T> // getResponse 默认是 false， 因此不提供该参数时，只返回 data
  <T = any>(url: string): Promise<T> // 不提供 opts 时，默认使用 'GET' method，并且默认返回 data
}
let requestInstance: AxiosInstance

const config: AxiosConfig = {
  baseURL: HOST,
  timeout: 3000,
  headers: { 'X-Custom-Header': 'foobar' },
  metadata: { startTime: Date.now() }
}

const getRequestInstance = (): AxiosInstance => {
  requestInstance = axios.create(config)
  requestInstance.interceptors.request.use((request) => {
    request.headers['Authorization'] = `Bearer ${localStorage.getItem('PROJECT_TOKEN')}`
    request.metadata = { startTime: Date.now() }
    // request.metadata.startTime = Date.now()
    return request
  })

  requestInstance.interceptors.response.use((response) => {
    response.config.metadata = {
      ...response.config.metadata,
      endTime: Date.now()
    }
    const duration = response.config.metadata.endTime! - response.config.metadata.startTime!
    console.log(`请求 ${response.config.url} 耗时 ${duration} ms`)
    return response
  })
  return requestInstance
}

const request: IRequest = (url: string, opts: any = { method: 'GET' }) => {
  const requestInstance = getRequestInstance()
  return new Promise((resolve, reject) => {
    requestInstance
      .request({ ...opts, url })
      .then((res) => {
        resolve(res.data)
      })
      .catch((error: AxiosError) => {
        reject(error)
        message.error(error.message)
      })
  })
}

export default request
